// src/api/fetch.ts 带缓存的请求
import { get, post, put, del } from '@/http/request'
import type { AxiosRequestConfig } from 'axios'
// 缓存管理
interface CacheItem<T> {
  data: T
  timestamp: number
  expiry: number
}
class RequestCache {
  private cache = new Map<string, CacheItem<any>>()
  private defaultTTL = 5 * 60 * 1000 // 默认5分钟过期
  // 生成缓存键
  private generateKey(url: string, params?: any, config?: AxiosRequestConfig): string {
    const keyObject = {
      url,
      params: params || {},
      headers: config?.headers || {},
    }
    return JSON.stringify(keyObject)
  }
  // 设置缓存
  set<T>(key: string, data: T, ttl?: number): void {
    const expiry = Date.now() + (ttl || this.defaultTTL)
    this.cache.set(key, {
      data,
      timestamp: Date.now(),
      expiry,
    })
  }
  // 获取缓存
  get<T>(key: string): T | null {
    const item = this.cache.get(key)
    if (!item) return null
    // 检查是否过期
    if (Date.now() > item.expiry) {
      this.cache.delete(key)
      return null
    }
    return item.data
  }
  // 清除缓存
  clear(pattern?: string): void {
    if (!pattern) {
      this.cache.clear()
      return
    }
    // 模糊匹配清除
    for (const key of this.cache.keys()) {
      if (key.includes(pattern)) {
        this.cache.delete(key)
      }
    }
  }
  // 获取缓存键（供外部使用）
  getKey(url: string, params?: any, config?: AxiosRequestConfig): string {
    return this.generateKey(url, params, config)
  }
}
// 创建缓存实例
const requestCache = new RequestCache()

/**
 * 封装 GET 请求方法
 * @param url 请求地址
 * @param params 请求参数
 * @param config 请求配置
 * @param cacheOptions 缓存选项
 */
export const getFetch = <T = any>(
  url: string,
  params?: any,
  cacheOptions?: {
    ttl?: number // 缓存时间（毫秒）
    noCache?: boolean // 跳过缓存
  },
  config?: AxiosRequestConfig,
) => {
  const cacheKey = requestCache.getKey(url, params, config)
  if (cacheOptions?.noCache) {
    return get<T>(url, { params, ...config })
  }
  const cachedData = requestCache.get<T>(cacheKey)
  if (cachedData) {
    return Promise.resolve(cachedData)
  }
  return get<T>(url, { params, ...config }).then((data) => {
    requestCache.set(cacheKey, data, cacheOptions?.ttl)
    return data
  })
}

/**
 * 封装 POST 请求方法（带缓存）
 * @param url 请求地址
 * @param data 请求数据
 * @param cacheOptions 缓存选项
 * @param config 请求配置
 */
export const postFetch = <T = any>(
  url: string,
  data?: any,
  cacheOptions?: {
    ttl?: number // 缓存时间（毫秒）
    noCache?: boolean // 跳过缓存
    clearCache?: string[] // 清除相关缓存的URL模式
  },
  config?: AxiosRequestConfig,
) => {
  const cacheKey = requestCache.getKey(url, data, config)
  if (cacheOptions?.noCache) {
    return post<T>(url, data, config).then((response) => {
      if (cacheOptions?.clearCache) {
        cacheOptions.clearCache.forEach((pattern) => {
          requestCache.clear(pattern)
        })
      }
      return response
    })
  }
  const cachedData = requestCache.get<T>(cacheKey)
  if (cachedData) {
    return Promise.resolve(cachedData)
  }
  return post<T>(url, data, config).then((response) => {
    requestCache.set(cacheKey, response, cacheOptions?.ttl)
    if (cacheOptions?.clearCache) {
      cacheOptions.clearCache.forEach((pattern) => {
        requestCache.clear(pattern)
      })
    }
    return response
  })
}

/**
 * 封装 PUT 请求方法（带缓存）
 * @param url 请求地址
 * @param data 请求数据
 * @param config 请求配置
 * @param cacheOptions 缓存选项
 */
export const putFetch = <T = any>(
  url: string,
  data?: any,
  cacheOptions?: {
    ttl?: number // 缓存时间（毫秒）
    noCache?: boolean // 跳过缓存
    clearCache?: string[] // 清除相关缓存的URL模式
  },
  config?: AxiosRequestConfig,
) => {
  const cacheKey = requestCache.getKey(url, data, config)
  if (cacheOptions?.noCache) {
    return put<T>(url, data, config).then((response) => {
      if (cacheOptions?.clearCache) {
        cacheOptions.clearCache.forEach((pattern) => {
          requestCache.clear(pattern)
        })
      }
      return response
    })
  }
  const cachedData = requestCache.get<T>(cacheKey)
  if (cachedData) {
    return Promise.resolve(cachedData)
  }
  return put<T>(url, data, config).then((response) => {
    requestCache.set(cacheKey, response, cacheOptions?.ttl)
    if (cacheOptions?.clearCache) {
      cacheOptions.clearCache.forEach((pattern) => {
        requestCache.clear(pattern)
      })
    }
    return response
  })
}
/**
 * 封装 DELETE 请求方法（带缓存）
 * @param url 请求地址
 * @param params 请求参数
 * @param config 请求配置
 * @param cacheOptions 缓存选项
 */
export const deleteFetch = <T = any>(
  url: string,
  params?: any,
  cacheOptions?: {
    ttl?: number // 缓存时间（毫秒）
    noCache?: boolean // 跳过缓存
    clearCache?: string[] // 清除相关缓存的URL模式
  },
  config?: AxiosRequestConfig,
) => {
  const cacheKey = requestCache.getKey(url, params, config)
  if (cacheOptions?.noCache) {
    return del<T>(url, { params, ...config }).then((response) => {
      if (cacheOptions?.clearCache) {
        cacheOptions.clearCache.forEach((pattern) => {
          requestCache.clear(pattern)
        })
      }
      return response
    })
  }
  const cachedData = requestCache.get<T>(cacheKey)
  if (cachedData) {
    return Promise.resolve(cachedData)
  }
  return del<T>(url, { params, ...config }).then((response) => {
    requestCache.set(cacheKey, response, cacheOptions?.ttl)
    if (cacheOptions?.clearCache) {
      cacheOptions.clearCache.forEach((pattern) => {
        requestCache.clear(pattern)
      })
    }
    return response
  })
}

// 导出缓存管理工具
export const cacheManager = {
  // 手动清除缓存
  clear: (pattern?: string) => requestCache.clear(pattern),
  // 清除所有缓存
  clearAll: () => requestCache.clear(),
  // 获取缓存键（用于调试）
  getKey: (url: string, params?: any, config?: AxiosRequestConfig) => requestCache.getKey(url, params, config),
}
